#include<stdio.h>
#include<string.h>
#include <unistd.h>
#include"../include/transportADT.h"
#include"../include/marshallADT.h"
#include"../include/cityDefs.h"
#include"../include/bondi.h"

#define MQ_KEY 108

//funciones que arman y desarman los paquetes de los mensajes, segun quien se comunique

static int marshallCityRecv(void * msg, char * buff);
static int marshallCitySend(char * msg, char * buff);
static int marshallCityStopSend(int * msg, char * buff);
static int marshallBusCRecv(char * info, char * buff);
static int marshallBusCSend(busReqT * msg, char * buff);
static int marshallTrafficLSend(semafT * msg, char * buff);
static int marshallTrafficLRecv(char * info, char * buff);
static int marshallStopSend(stops_t * msg, char * buff);
static int marshallPasLogSend(passData_T * msg, char * buff);
static int marshallLineSend(char * ans, char * buff);
static int marshallLineRecv(stopReqT * msg, char * buff);
static int marshallBusLSend(stopReqT * msg, char * buff);
static int marshallBusLRecv(char * info, char * buff);
static int marshallStopRecv(int * info, char * buff);

marshallADT
openMarsh(int id) {
	return openTrans(&id);
}

marshallADT
getMarsh(int id, int dest) {
	return getTrans(&id, &dest);
}

void
closeMarsh(marshallADT mar) {
	return closeTrans(mar);
}

int
sendData(marshallADT mar, void * info, int type) {
	char buff[MSG_LEN+1];
	int size;

	switch(type) {
		case CITY: size=marshallCitySend(info, buff); break;
		case BUS_C: size=marshallBusCSend(info, buff); break;
		case STOP: size=marshallStopSend(info, buff); break;
		case PASSENGER: size=marshallPasLogSend(info, buff); break;
		case LINE: size=marshallLineSend(info, buff); break;
		case BUS_L: size=marshallBusLSend(info, buff); break;
		case CITY_STOP: size=marshallCityStopSend(info, buff); break;
		case TRAFFIC_LIGHT: size=marshallTrafficLSend(info, buff); break;
	default: break;
	}

	int cant = -1;

	if(size<=0)
		return -1;							//error de mens
	//escribe el mensaje de buffer con el tamaño especifico
	if( (cant = writeMsg(mar, buff, size))==-1) {
		return -2;							//error de escritura
	}

	return cant;
}

int
recvData(marshallADT mar, void * buff, int type) {
	char buffaux[MSG_LEN+1];

	switch(type) {
		case CITY:
			//leo el tamano del mensaje
			if(readMsg(mar, buffaux, 8)!=-1)
				//llamo a la funcion indicada con lo leido del transporte
				return marshallCityRecv(buff, buffaux);
			break;
		case BUS_C:
			if(readMsg(mar, buffaux, 1)!=-1)
				return marshallBusCRecv(buff, buffaux);
			break;
		case TRAFFIC_LIGHT:
			if(readMsg(mar, buffaux, 1)!=-1) {
				marshallTrafficLRecv(buff, buffaux);
				return 1;
			}
			break;
		case LINE:
			if(readMsg(mar, buffaux, 2)!=-1) {
				marshallLineRecv(buff, buffaux);
				return 1;
			}
			break;
		case BUS_L:
			if(readMsg(mar, buffaux, 1)!=-1) {
				marshallBusLRecv(buff, buffaux);
				return 1;
			}
			break;
		case STOP:
			if(readMsg(mar, buffaux, 4)!=-1) {
				marshallStopRecv(buff, buffaux);
				return 1;
			}
			break;
	default: break;
	}

	return -1;
}

//devuelve un codigo para que la ciudad sepa que hacer
static int
marshallCityRecv(void * info, char * buff) {

	switch(buff[0]){
	case STOP: {stops_t * msg = (stops_t *)info;
				msg->type = buff[0];
				msg->pos.x = buff[1];
				msg->pos.y = buff[2];
				msg->linea = buff[3];
				msg->paradaNInterno = buff[4];
				return STOP;}break;
	case PASSENGER: {	passData_T * msg = (passData_T *)info;
						msg->type = buff[0];
						msg->paradaOr = buff[1];
						msg->paradaDest = buff[2];
						msg->linea = buff[3];
						msg->status = buff[4];
						msg->numeroPas = buff[5];
						msg->bondi = buff[6];
						return PASSENGER;};break;
	case TRAFFIC_LIGHT_HOR: case TRAFFIC_LIGHT_VER: {semafT * msg = (semafT *)info;
													msg->status = buff[0];
													msg->pos.x = buff[1];
													msg->pos.y = buff[2];
													msg->intervalo = buff[3];
													return TRAFFIC_L_SWITCH;} break;
	case BUS_CREATE: case BUS_MOVE:{ 	busReqT * msg = (busReqT *)info;
				msg->type = buff[0];
				msg->busN = buff[1];
				msg->busLine = buff[2];
				msg->curPos.x = buff[3];
				msg->curPos.y = buff[4];
				msg->move = buff[5];
				msg->orientation = buff[6];
				msg->pasajeros = buff[7];

				return (int)buff[0];
			}break;
	}

	return -1;
}

static int
marshallCitySend(char * msg, char * buff) {

	buff[0]= *msg;

	return 1;
}

static int
marshallCityStopSend(int * msg, char * buff) {

	buff[0]= *msg;

	return 4;
}

static int
marshallBusCSend(busReqT * msg, char * buff) {

	buff[0] = msg->type;
	buff[1] = msg->busN;
	buff[2] = msg->busLine;
	buff[3] = msg->curPos.x;
	buff[4] = msg->curPos.y;
	buff[5] = msg->move;
	buff[6] = msg->orientation;
	buff[7] = msg->pasajeros;

	return 8;
}

static int
marshallBusCRecv(char * info, char * buff) {

	*info = buff[0];

	return 0;
}

static int
marshallTrafficLSend(semafT * msg, char * buff) {

	buff[0] = msg->status;
	buff[1] = msg->pos.x;
	buff[2] = msg->pos.y;
	buff[3] = msg->intervalo;

	return 4;
}

static int
marshallTrafficLRecv(char * info, char * buff) {

	*info = buff[0];

	return 0;
}

static int
marshallPasLogSend(passData_T * msg, char * buff){

	buff[0] = msg->type;
	buff[1] = msg->paradaOr;
	buff[2] = msg->paradaDest;
	buff[3] = msg->linea;
	buff[4] = msg->status;
	buff[5] = msg->numeroPas;
	buff[6] = msg->bondi;

	return 7;
}

static int
marshallStopSend(stops_t * msg, char * buff) {

	buff[0] = msg->type;
	buff[1] = msg->pos.x;
	buff[2] = msg->pos.y;
	buff[3] = msg->linea;
	buff[4] = msg->paradaNInterno;

	return 5;
}

static int
marshallLineRecv(stopReqT * msg, char * buff){
	msg->nrobondi = buff[0];
	msg->parada = buff[1];

	return 0;
}

static int
marshallLineSend(char * ans, char * buff) {

	buff[0] = *ans;

	return 1;
}

static int
marshallBusLRecv(char * info, char * buff) {

	*info = buff[0];

	return 0;
}

static int
marshallBusLSend(stopReqT * msg, char * buff) {

	buff[0] = msg->nrobondi;
	buff[1] = msg->parada;

	return 2;
}

static int
marshallStopRecv(int * info, char * buff) {

	*info = buff[0];

	return 0;
}
